#include "i2c.h"
#include "delay.h"
static void myI2cInit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C_SDA | I2C_SCL;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    I2C_SCL_H;
    I2C_SDA_H;
}

static void myI2cDeinit(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = I2C_SDA | I2C_SCL;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    I2C_DeInit(I2C1);
}
static void sdaOut(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C_SDA;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

static void sdaIn(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    GPIO_InitStructure.GPIO_Pin = I2C_SDA;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
}

static void start(void)
{
    sdaOut();
    I2C_SDA_H;
    I2C_SCL_H;
    Delay_us(5);
    I2C_SDA_L;
    Delay_us(6);
    I2C_SCL_L;
}

static void stop(void)
{
    sdaOut();
    I2C_SDA_L;
    I2C_SCL_L;
    Delay_us(5);
    I2C_SCL_H;
    Delay_us(6);
    I2C_SDA_H;
    Delay_us(6);
}

static void sendAck(void)
{
    sdaOut();
    I2C_SCL_L;
    I2C_SDA_L;
    Delay_us(2);
    I2C_SCL_H;
    Delay_us(5);
    I2C_SCL_L;
}

static void sendNack(void)
{
    sdaOut();
    I2C_SCL_L;
    I2C_SDA_H;
    Delay_us(2);
    I2C_SCL_H;
    Delay_us(5);
    I2C_SCL_L;
}

static u8 waitAck(void)
{
    u8 time = 0;
    sdaIn();
    I2C_SDA_H;
    Delay_us(2);
    I2C_SCL_H;
    Delay_us(2);
    while (GPIO_ReadInputDataBit(GPIO_I2C, I2C_SDA))
    {
        time++;
        Delay_us(1);
        if (time > 250)
        {
            stop();
            return 1;
        }
    }
    I2C_SCL_L;
    return 0;
}

static void sendByte(char Byte)
{
    u8 i = 0;
    sdaOut();
    I2C_SCL_L;
    for (i = 0; i < 8; i++)
    {
        if (Byte & 0x80)
        {
            I2C_SDA_H;
        }
        else
        {
            I2C_SDA_L;
        }
        Byte <<= 1;
        I2C_SCL_H;
        Delay_us(6);
        I2C_SCL_L;
        Delay_us(6);
    }
}

static u8 recievedByte(u8 ack)
{
    u8 i = 0, receive = 0;
    sdaIn();
    for (i = 0; i < 8; i++)
    {
        I2C_SCL_L;
        Delay_us(2);
        I2C_SCL_H;
        while (!GPIO_ReadInputDataBit(GPIO_I2C, I2C_SCL))
            ;
        receive <<= 1;
        if (GPIO_ReadInputDataBit(GPIO_I2C, I2C_SDA))
            receive++;
        Delay_us(1);
    }
    if (ack == 0)
        sendNack();
    else
        sendAck();
    return receive;
}

static void I2cDeinit(void)
{

    GPIO_InitTypeDef GPIO_Struct;
    GPIO_StructInit(&GPIO_Struct);
    GPIO_StructInit(&GPIO_Struct);
    GPIO_Struct.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Struct.GPIO_Pin = I2C_SCL | I2C_SDA;
    GPIO_Init(GPIO_I2C, &GPIO_Struct);
}
i2c_t *i2CCreate(void)
{
    static i2c_t i2c;
    i2c.Pi2cInit = myI2cInit;
    i2c.Pi2cDeinit = myI2cDeinit;
    i2c.Pi2cSdaOut = sdaOut;
    i2c.Pi2cSdaIn = sdaIn;
    i2c.Pi2cStart = start;
    i2c.Pi2cStop = stop;
    i2c.Pi2csendAck = sendAck;
    i2c.Pi2csendNack = sendNack;
    i2c.Pi2cWaitAck = waitAck;
    i2c.Pi2cReciveByte = recievedByte;
    i2c.Pi2cSendByte = sendByte;
    return &i2c;
}
